package main

import (
	"fmt"
	"time"
)

//数组
//切片
//map

func main() {
	fmt.Println("---------slice")
	sliceTest()
	fmt.Println("---------map")
	mapTest()
	fmt.Println("---------chan")
	channelTest()
	fmt.Println("---------range")
	rangeTest()
}

func sliceTest() {
	var numbers3 = [5]int{1, 2, 3, 4, 5}
	slice3 := numbers3[2: len(numbers3)] //3
	length := (3)
	capacity := (3)
	fmt.Printf("%v, %v\n", (length == len(slice3)), (capacity == cap(slice3)))
	fmt.Printf("\n")

	//true, true
	//true
	//true, true, true
	var numbers4 = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	slice5 := numbers4[4:6:8]
	length = (2)
	capacity = (4)
	fmt.Printf("%v, %v\n", length == len(slice5), capacity == cap(slice5))

	slice5 = slice5[:cap(slice5)] //5,6,78
	//fmt.Println(slice5)
	slice5 = append(slice5, 11, 12, 13)
	//fmt.Println(slice5)
	length = (7)
	fmt.Printf("%v\n", length == len(slice5))
	slice6 := []int{0, 0, 0}
	copy(slice5, slice6)
	fmt.Println(slice5)
	e2 := (0)
	e3 := (8)
	e4 := (11)
	fmt.Printf("%v, %v, %v\n", e2 == slice5[2], e3 == slice5[3], e4 == slice5[4])

}

func mapTest() {
	//25, 50, 0
	mm2 := map[string]int{"golang": 42, "java": 1, "python": 8}
	mm2["scala"] = 25
	mm2["erlang"] = 50
	mm2["python"] = 0
	fmt.Printf("%d, %d, %d \n", mm2["scala"], mm2["erlang"], mm2["python"])
}

type Sender chan<- int

type Receiver <-chan int

func channelTest() {
	ch2 := make(chan string, 1)
	// 下面就是传说中的通过启用一个Goroutine来并发的执行代码块的方法。
	// 关键字 go 后跟的就是需要被并发执行的代码块，它由一个匿名函数代表。
	// 对于 go 关键字以及函数编写方法，我们后面再做专门介绍。
	// 在这里，我们只要知道在花括号中的就是将要被并发执行的代码就可以了。
	go func() {
		ch2 <- ("已到达！")
	}()
	var value string = "数据"
	value = value + <-ch2
	fmt.Println(value)

	//更多用法Chapter5.go:72
	//Received! 6
	//Sent!
	var myChannel = make(chan int, 0)
	var number = 6
	go func() {
		var sender Sender = myChannel
		sender <- number
		fmt.Println("Sent!")
	}()
	go func() {
		var receiver Receiver = myChannel
		fmt.Println("Received!", <-receiver)
	}()
	// 让main函数执行结束的时间延迟1秒，
	// 以使上面两个代码块有机会被执行。
	time.Sleep(time.Second)
}

func rangeTest() {
	//这是我们使用range去求一个slice的和。使用数组跟这个很类似
	nums := []int{2, 3, 4}
	sum := 0
	for _, num := range nums {
		sum += num
	}
	fmt.Println("sum:", sum)
	//在数组上使用range将传入index和值两个变量。上面那个例子我们不需要使用该元素的序号，所以我们使用空白符"_"省略了。有时侯我们确实需要知道它的索引。
	for i, num := range nums {
		if num == 3 {
			fmt.Println("index:", i)
		}
	}
	//range也可以用在map的键值对上。
	kvs := map[string]string{"a": "apple", "b": "banana"}
	for k, v := range kvs {
		fmt.Printf("%s -> %s\n", k, v)
	}
	//range也可以用来枚举Unicode字符串。第一个参数是字符的索引，第二个是字符（Unicode的值）本身。
	for i, c := range "go" {
		fmt.Println(i, c)
	}
}
